#! /usr/bin/env python
# -*- coding: utf8 -*-
"""Port of NeHe Lesson 16 by Ivan Izuver <izuver@users.sourceforge.net>"""
import string

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import sys
import Image
from lib import *

# Some api in the chain is translating the keystrokes to this octal string
# so instead of saying: ESCAPE = 27, we use the following.
ESCAPE = '\033'

# Number of the glut window.
window = 0

# Rotations for cube. 
xrot=yrot=zrot=0.0
xspeed=yspeed=zspeed=0.0

texture = 0
fname	= r'D:\me\picture\game\vos\loading02.jpg'

object	= 0

def LoadTextures(fname):
	#global texture
	im		= Image.open(fname)
	width, height	= im.size
	im		= im.tostring("raw", "RGBX", 0, -1)
	
	# 生成id并将其指定为当前的纹理id
	idTexture	= glGenTextures(1)
	glBindTexture(GL_TEXTURE_2D, idTexture)
	
	# 控制所读取图像数据的行对齐方式，默认4字节对齐,即一行的图像数据的字节数必须为4的整数倍，如果控制不好的话，会发生数据跨行读取，从而图像混乱
	print(width, height)
	# glPixelStorei(GL_UNPACK_ALIGNMENT, 8)

	# copy图片数据到当前的纹理对象
	glTexImage2D(GL_TEXTURE_2D, # 必须是GL_TEXTURE_2D
			0,					# level，表示多级分辨率的纹理图像的级数，若只有一咱分辨率，则设置level为0 
			GL_RGB,				# 指出使用了RGBA中的哪些分量用于调整和混合
			width, height, 
			0, 					# 边界宽度，0代表没有，1代表有
			GL_RGBA, 
			GL_UNSIGNED_BYTE, 
			im)					# 纹理图像数据

	# glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
	# glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

	# 纹理组合器函数：指定纹理贴图和材料混合的方式
	# GL_MODULATE	调合(默认)，根据纹理图像的内容对片断的内容进行调整,内部格式为GL_RGB和GL_RGBA时, 片断颜色的各个分量与纹理中相应的分量相乘, alpha值也同片断alpha相乘. 光照适合使用纹理映射方式调整
	# GL_REPLACE	替换，用纹理颜色替换片断的颜色
	# GL_DECAL		贴花，与替换类似，只适用于RGB和RGBA。当内部格式为RGBA时，会将片断的颜色与纹理的颜色混合，混合比率由纹理的alpha决定，片断的alpha不变
	# GL_ADD		相加，将纹理颜色与片断颜色相加，如有alpha值，其乘以片断的alpha值
	# glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
	# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
	# glEnable(GL_BLEND)

	glEnable(GL_COLOR_MATERIAL)
	glColorMaterial(GL_FRONT, GL_DIFFUSE)
	glColor3f(0, 1.0, 0)

# A general OpenGL initialization function.  Sets all of the initial parameters. 
def InitGL(width, height):				  # We call this right after our OpenGL window is created.
	global quadratic
	global fname
	LoadTextures(fname)
	
	# 创建一个二次对象
	quadratic	= gluNewQuadric()
	# 二次对象使用的法向量类型
	gluQuadricNormals(quadratic, GLU_SMOOTH)		# Create Smooth Normals (NEW) 
	# 指定二次对象是否使用纹理
	gluQuadricTexture(quadratic, GL_TRUE)			 # Create Texture Coords (NEW)
	 
	# glEnable(GL_TEXTURE_2D)
	glClearColor(0.0, 0.0, 0.0, 0.0)	# This Will Clear The Background Color To Black
	glClearDepth(1.0)					 # Enables Clearing Of The Depth Buffer
	glDepthFunc(GL_LESS)				# The Type Of Depth Test To Do
	glEnable(GL_DEPTH_TEST)				   # Enables Depth Testing
	glShadeModel(GL_SMOOTH)				   # Enables Smooth Color Shading

##	  glPolygonMode(GL_FRONT, GL_LINE)
##	  glPolygonMode(GL_BACK, GL_LINE)
	
	# 自动生成纹理坐标
	mode	= GL_OBJECT_LINEAR
	mode	= GL_SPHERE_MAP
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, mode)
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, mode)
	
	# glMatrixMode(GL_PROJECTION)
	# glLoadIdentity()					# Reset The Projection Matrix
										# Calculate The Aspect Ratio Of The Window
	# gluPerspective(60.0, float(width)/float(height), 0.1, 100.0)

	# glMatrixMode(GL_MODELVIEW)

# The function called when our window is resized (which shouldn't happen if you enable fullscreen, below)
def ReSizeGLScene(width, height):
	print(width, height)
	if height == 0:						   # Prevent A Divide By Zero If The Window Is Too Small 
		height = 1

	glViewport(0, 0, width, height)		   # Reset The Current Viewport And Perspective Transformation
	glMatrixMode(GL_PROJECTION)
	glLoadIdentity()
	gluPerspective(60.0, float(width)/float(height), 0.1, 100.0)
	glMatrixMode(GL_MODELVIEW)


def DrawLine(v1, v2):
	glLoadIdentity()
	glBegin(GL_LINES)
	glVertex(v1)
	glVertex(v2)
	glEnd()

# The main drawing function. 
def DrawGLScene():
	global xrot, yrot, zrot, texture,quadratic

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)	  # Clear The Screen And The Depth Buffer

	glColor3f(1.0, 0, 0)
	glLoadIdentity()
	glTranslatef(0, 0, -5)

	glBegin(GL_LINES)
	glVertex((1, 2, 0))
	# glVertex((1, -1, 0))
	glVertex((-1, -1, 0))
	glEnd()

	#  since this is double buffered, swap the buffers to display what just got drawn. 
	glutSwapBuffers()

# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)	
def keyPressed(key,x,y):
	global object
	# If escape is pressed, kill everything.
	key = string.upper(key)
	if key == ESCAPE:
		sys.exit()
	elif key == 'L':
		light = not light
	elif key == 'T': #	switch the texture
		texture_num = (texture_num + 1) % 3
	elif key == 'O': #	switch the object
		object = (object + 1) % 7

def main():
	global window
	glutInit(sys.argv)

	# Select type of Display mode:	 
	#  Double buffer 
	#  RGBA color
	# Alpha components supported 
	# Depth buffer
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
	
	# get a 640 x 480 window 
	glutInitWindowSize(800, 600)
	
	# the window starts at the upper left corner of the screen 
	glutInitWindowPosition(100, 100)
	
	# Okay, like the C version we retain the window id to use when closing, but for those of you new
	# to Python (like myself), remember this assignment would make the variable local and not global
	# if it weren't for the global declaration at the start of main.
	window = glutCreateWindow("Spheric by RISC")

	   # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to
	# set the function pointer and invoke a function to actually register the callback, otherwise it
	# would be very much like the C version of the code.	
	glutDisplayFunc(DrawGLScene)
	
	# Uncomment this line to get full screen.
	# glutFullScreen()

	# When we are doing nothing, redraw the scene.
	glutIdleFunc(DrawGLScene)
	
	# Register the function called when our window is resized.
	glutReshapeFunc(ReSizeGLScene)
	
	# Register the function called when the keyboard is pressed.  
	glutKeyboardFunc(keyPressed)

	# Initialize our window. 
	InitGL(640, 480)

	# Start Event Processing Engine    
	glutMainLoop()

# Print message to console, and kick off the main to get it rolling.
if __name__ == "__main__":
	print "Hit ESC key to quit."
	main()
		
